package com.njmaomao.gj.pyot.domain.wechat.wechatapi.unifiedorder;

import com.njmaomao.gj.pyot.common.Utils;
import com.njmaomao.gj.pyot.config.Bizs;
import com.njmaomao.gj.pyot.domain.wechat.PayConfig;
import com.njmaomao.gj.pyot.domain.wechat.PaymentOrder;
import com.thoughtworks.xstream.annotations.XStreamAlias;

/**
 * 统一下单入参
 * @author hh 2018-5-10
 */
@XStreamAlias("xml")
public class UnifiedorderReq {

    // 公众账号ID 必填[是] 微信支付分配的公众账号ID（企业号corpid即为此appId）、微信开放平台审核通过的应用APPID、小程序ID
    private String appid;

    // 商户号 必填[是] 微信支付分配的商户号
    @XStreamAlias("mch_id")
    private String mchId;

    // 设备号 必填[否] 自定义参数，可以为终端设备号(门店号或收银设备ID)，PC网页或公众号内支付可以传"WEB"
    @XStreamAlias("device_info")
    private String deviceInfo;

    // 随机字符串 必填[是] 随机字符串，长度要求在32位以内。推荐随机数生成算法
    @XStreamAlias("nonce_str")
    private String nonceStr;

    // 签名 必填[是] 通过签名算法计算得出的签名值，详见签名生成算法
    private String sign;

    // 签名类型 必填[否] 签名类型，默认为MD5，支持HMAC-SHA256和MD5。
    @XStreamAlias("sign_type")
    private String signType;

    // 商品描述 必填[是] 商品简单描述，该字段请按照规范传递，具体请见参数规定
    private String body;

    // 商品详情 必填[否] 商品详细描述，对于使用单品优惠的商户，改字段必须按照规范上传，详见“单品优惠参数说明”
    private String detail;

    // 附加数据 必填[否] 附加数据，在查询API和支付通知中原样返回，可作为自定义参数使用。
    private String attach;

    // 商户订单号 必填[是] 商户系统内部订单号，要求32个字符内，只能是数字、大小写字母_-|* 且在同一个商户号下唯一。详见商户订单号
    @XStreamAlias("out_trade_no")
    private String outTradeNo;

    // 标价币种 必填[否] 符合ISO 4217标准的三位字母代码，默认人民币：CNY，详细列表请参见货币类型
    @XStreamAlias("fee_type")
    private String feeType;

    // 标价金额 必填[是] 订单总金额，单位为分，详见支付金额
    @XStreamAlias("total_fee")
    private int totalFee;

    // 终端IP 必填[是] APP和网页支付提交用户端ip，Native支付填调用微信支付API的机器IP。
    @XStreamAlias("spbill_create_ip")
    private String spbillCreateIp;

    // 交易起始时间 必填[否] 订单生成时间，格式为yyyyMMddHHmmss，如2009年12月25日9点10分10秒表示为20091225091010。其他详见时间规则
    @XStreamAlias("time_start")
    private String timeStart;

    // 交易结束时间 必填[否] 订单失效时间，格式为yyyyMMddHHmmss，如2009年12月27日9点10分10秒表示为20091227091010。订单失效时间是针对订单号而言的，由于在请求支付的时候有一个必传参数prepay_id只有两小时的有效期，所以在重入时间超过2小时的时候需要重新请求下单接口获取新的prepay_id。其他详见时间规则建议：最短失效时间间隔大于1分钟
    @XStreamAlias("time_expire")
    private String timeExpire;

    // 订单优惠标记 必填[否] 订单优惠标记，使用代金券或立减优惠功能时需要的参数，说明详见代金券或立减优惠
    @XStreamAlias("goods_tag")
    private String goodsTag;

    // 通知地址 必填[是] 异步接收微信支付结果通知的回调地址，通知url必须为外网可访问的url，不能携带参数。
    @XStreamAlias("notify_url")
    private String notifyUrl;

    // 交易类型 必填[是] JSAPI-公众号/小程序支付 NATIVE-扫码支付 APP-APP支付 说明详见参数规定
    @XStreamAlias("trade_type")
    private String tradeType;

    // 商品ID 必填[否] trade_type=NATIVE时（即扫码支付），此参数必传。此参数为二维码中包含的商品ID，商户自行定义。
    @XStreamAlias("product_id")
    private String productId;

    // 指定支付方式 必填[否] 上传此参数no_credit--可限制用户不能使用信用卡支付
    @XStreamAlias("limit_pay")
    private String limitPay;

    // 用户标识 必填[否] trade_type=JSAPI时（即公众号支付），此参数必传，此参数为微信用户在商户对应appid下的唯一标识。openid如何获取，可参考【获取openid】。企业号请使用【企业号OAuth2.0接口】获取企业号内成员userid，再调用【企业号userid转openid接口】进行转换
    private String openid;

    // 场景信息 场景信息 必填[否] 该字段用于上报场景信息，目前支持上报实际门店信息。该字段为JSON对象数据，对象格式为{"store_info":{"id": "门店ID","name": "名称","area_code": "编码","address": "地址" }} ，字段详细说明请点击行前的+展开
    /**
     * App支付格式：
     *{
     *"store_id": "", //门店唯一标识，选填，String(32)
     *"store_name":"”//门店名称，选填，String(64)
     *}
     */
    @XStreamAlias("scene_info")
    private String sceneInfo;

    /**
     *
     * @param clazz
     * @param <T> AppSceneInfo.class 或 SceneInfo.class
     * @return
     */
    public <T> T getSceneInfo(Class<T> clazz) {
        return Utils.toObj(this.sceneInfo, clazz);
    }

    public String getAppid() {
        return appid;
    }

    public String getMchId() {
        return mchId;
    }

    public String getDeviceInfo() {
        return deviceInfo;
    }

    public String getNonceStr() {
        return nonceStr;
    }

    public String getSign() {
        return sign;
    }

    public String getSignType() {
        return signType;
    }

    public String getBody() {
        return body;
    }

    public String getDetail() {
        return detail;
    }

    public String getAttach() {
        return attach;
    }

    public String getOutTradeNo() {
        return outTradeNo;
    }

    public String getFeeType() {
        return feeType;
    }

    public int getTotalFee() {
        return totalFee;
    }

    public String getSpbillCreateIp() {
        return spbillCreateIp;
    }

    public String getTimeStart() {
        return timeStart;
    }

    public String getTimeExpire() {
        return timeExpire;
    }

    public String getGoodsTag() {
        return goodsTag;
    }

    public String getNotifyUrl() {
        return notifyUrl;
    }

    public String getTradeType() {
        return tradeType;
    }

    public String getProductId() {
        return productId;
    }

    public String getLimitPay() {
        return limitPay;
    }

    public String getOpenid() {
        return openid;
    }

    public static UnifiedorderReq build(PaymentOrder order, PayConfig payConfig, String openId, String tradeType) {

        UnifiedorderReq unifiedorderReq = new UnifiedorderReq();

        unifiedorderReq.appid = payConfig.getAppid();
        unifiedorderReq.mchId = payConfig.getMchId();
        unifiedorderReq.signType = Bizs.SIGN_TYPE;
        unifiedorderReq.notifyUrl = payConfig.getPayNotifyUrl();
        unifiedorderReq.tradeType = tradeType;

        unifiedorderReq.nonceStr = Bizs.generateNonceStr();
        unifiedorderReq.body = order.orderDesc();
        unifiedorderReq.outTradeNo = order.orderCode();
        unifiedorderReq.totalFee = order.txnAmt();
        unifiedorderReq.spbillCreateIp = Bizs.spbillCreateIp();
        unifiedorderReq.openid = openId;

        unifiedorderReq.feeType = "CNY";

        unifiedorderReq.sign = Bizs.getMd5Sign(unifiedorderReq, payConfig.getKey());
        return unifiedorderReq;

    }

}
